﻿using Abp.Auditing;
using Abp.Authorization;
using Abp.Extensions;
using Abp.Localization;
using Abp.Runtime.Session;
using Abp.UI;
using Mt.Site.Application.Localization.Dto;
using Mt.Site.Core.Base.Localization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Mt.Site.Application.Localization
{
    [AbpAuthorize]
    public class FindLanguageAppService : MtSiteAppServiceBase, IFindLanguageAppService
    {
        private readonly IApplicationLanguageManager _applicationLanguageManager;

        public FindLanguageAppService(
            IApplicationLanguageManager applicationLanguageManager)
        {
            _applicationLanguageManager = applicationLanguageManager;
        }

        [DisableAuditing]
        public async Task<GetLanguagesForSelectionOutput> GetHostLanguages()
        {
            var languages = (await _applicationLanguageManager.GetLanguagesOfSingleTenantAsync(null))
                .OrderBy(l => l.DisplayName)
                .Select(l => l.ToLanguageInfo())
                .ToList();

            if (languages.Count <= 0)
            {
                throw new UserFriendlyException("No language defined in this application.");
            }

            var currentCultureName = Thread.CurrentThread.CurrentUICulture.Name;

            //Try to find exact match
            var currentLanguage = languages.FirstOrDefault(l => l.Name == currentCultureName);
            if (currentLanguage == null)
            {
                //Try to find best match
                currentLanguage = languages.FirstOrDefault(l => currentCultureName.StartsWith(l.Name));
            }
            if (currentLanguage == null)
            {
                //Try to find default language
                currentLanguage = languages.FirstOrDefault(l => l.IsDefault);
            }
            if (currentLanguage == null)
            {
                //Get first one
                currentLanguage = languages[0];
            }

            return new GetLanguagesForSelectionOutput(languages, currentLanguage);
        }

        [DisableAuditing]
        public async Task<GetLanguagesForSelectionOutput> GetTenantLanguages()
        {
            var tenantId = AbpSession.GetTenantId();
            var languages = (await _applicationLanguageManager.GetLanguagesOfSingleTenantAsync(tenantId))
                .OrderBy(l => l.DisplayName)
                .Select(l => l.ToLanguageInfo())
                .ToList();

            if (languages.Count <= 0)
            {
                throw new UserFriendlyException($"No language defined in for tenant: {tenantId}.");
            }

            var currentCultureName = AbpSession.CultureName();

            LanguageInfo currentLanguage = null;
            if (!currentCultureName.IsNullOrWhiteSpace())
            {
                currentLanguage = languages.FirstOrDefault(l => l.Name == currentCultureName);
                if (currentLanguage != null)
                {
                    return new GetLanguagesForSelectionOutput(languages, currentLanguage);
                }
            }

            currentLanguage = languages[0];
            var user = await GetCurrentUserAsync();
            user.CultureName = currentLanguage.Name;
            await UserManager.UpdateAsync(user);   

            return new GetLanguagesForSelectionOutput(languages, currentLanguage);
        }
    }
}
